/* 
 * File:   wiwannBuffer.h
 * Author: manu
 *
 * Created on 1 décembre 2010, 15:55
 */

#ifndef _WIWANNBUFFER_H
#define	_WIWANNBUFFER_H

#include "wiwannTypes.h" 
#include "wiwannBaseBuffer.h" 

#include <list>
#include <iterator>

//queue and unqueue dynamic arbiratry data

class wiwannBuffer
{
    private:
        std::list<wiwannBaseBuffer*> *lBaseBuffers ;

        void queue(wiwannBaseBuffer * wwbBB)
        {
            this->lBaseBuffers->empty() ;
                this->rewind();
            this->lBaseBuffers->push_back(wwbBB);
        }

        void queueClone(wiwannBaseBuffer * wwbB);
        


    public:
        std::iterator iBaseBuffers ;
        wiwannBuffer()
        {
            this->lBaseBuffers = new std::list<wiwannBaseBuffer*> ;
            this->rewind();
        }

        ~wiwannBuffer()
        {
          while (!  this->lBaseBuffers->empty())
          {
                delete this->lBaseBuffers->back() ;
                this->lBaseBuffers->pop_back();
          }
          delete this->lBaseBuffers  ;
        }

        wiwannBaseBuffer *getFrontBaseBuffer()
        {
            if( this->lBaseBuffers->empty() )
            {
                return NULL ;
            }
            return this->lBaseBuffers->front();
        }

        WIWANNsize getContigousChars()
        {
            if(this->getCurrentBaseBuffer()->isAtStart())
                return this->getCurrentBaseBuffer()->getSize();
            return 0 ;
        }

        void consume(WIWANNdontcare * wwp,WIWANNsize sizeChar)
        {
            if(sizeChar > 0 && this->getCurrentBaseBuffer()  )
            {
                if( sizeChar >= this->getContigousChars() )
                {
                    wwp = this->getCurrentBaseBuffer()->consume() ;
                }
                else
                {
                    wwp = this->getCurrentBaseBuffer()->read(wwp,sizeChar)
                }
                this->dropCurrentBaseBuffer();
            }
            wwp = NULL ;
        }

        void dropCurrentBaseBuffer()
        {
            std::iterator oldIterator = this->iBaseBuffers ;
            ++ this->iBaseBuffers ;

            delete oldIterator ;
            this->lBaseBuffers->erase(oldIterator);
        }

        void get(const WIWANNdontcare * wwp,WIWANNsize sizeChar)
        {
            WIWANNsize restingSize = this->getFrontBaseBuffer()->getRestingSize() ;
            if(  this->getFrontBaseBuffer() && ! this->getFrontBaseBuffer()->get(wwp,sizeChar) )
            {
                this->getFrontBaseBuffer()->get(wwp,restingSize) ;
                ++this->iBaseBuffers ;
                this->get(wwp + restingSize, sizeChar - restingSize );
            }
        }

        wiwannBaseBuffer * getCurrentBaseBuffer()
        {
            return * this->iBaseBuffers ;
        }




        void rewind()
        {
            this->iBaseBuffers = this->lBaseBuffers->begin() ;
        }

         wiwannBaseBuffer * next()
         {
             this->unqueue();
             return this->getFrontBaseBuffer() ;
         }

        wiwannBaseBuffer * unqueue()
        {
            wiwannBaseBuffer * wwnBB= this->getFrontBaseBuffer();
            this->lBaseBuffers->pop_front();
            return wwnBB ;
        }

        void queue(WIWANNdontcare * wwp,WIWANNsize sizeChar )
        {
            wiwannBaseBuffer *wwnBB = wiwannBaseBuffer::makeFromData(wwp,sizeChar);
            this->queue(wwnBB);
        }
        

        void queueClone(const WIWANNdontcare * wwp,WIWANNsize sizeChar )
        {
            wiwannBaseBuffer *wwnBB = wiwannBaseBuffer::cloneFromData(wwp,sizeChar);
            this->queue(wwnBB);
        }
    
};

#endif	/* _WIWANNBUFFER_H */

